home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2007 December / PCWKCD1207B.iso / Blogowanie poza sfera / Flock 0.9.1.3 stable / flock-0.9.1.3.en-US.win32.exe / flock / components / flockMagnoliaService.js < prev    next >
Text File  |  2007-10-12  |  20KB  |  562 lines

  1. // BEGIN FLOCK GPL
  2. // 
  3. // Copyright Flock Inc. 2005-2007
  4. // http://flock.com
  5. // 
  6. // This file may be used under the terms of of the
  7. // GNU General Public License Version 2 or later (the "GPL"),
  8. // http://www.gnu.org/licenses/gpl.html
  9. // 
  10. // Software distributed under the License is distributed on an "AS IS" basis,
  11. // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. // for the specific language governing rights and limitations under the
  13. // License.
  14. // 
  15. // END FLOCK GPL
  16. //
  17.  
  18. const ENABLE_DEBUG = true; // switch to turn off slow debug code for production
  19. function DEBUG(x) { if (ENABLE_DEBUG) debug("flockMagnoliaService: "+x+"\n"); }
  20.  
  21. const Cc = Components.classes;
  22. const Ci = Components.interfaces;
  23. const Cr = Components.results;
  24. const Cu = Components.utils;
  25.  
  26. const CLASS_ID                      = Components.ID ('{7c9aa278-85ed-4cbe-b0bc-f35df0978ade}');
  27. const CLASS_NAME                    = "Flock Magnolia Service";
  28. const CONTRACT_ID                   = "@flock.com/magnolia-service;1";
  29. const SERVICE_ENABLED_PREF          = "flock.service.magnolia.enabled";
  30. const CATEGORY_COMPONENT_NAME       = "Magnolia JS Component"
  31. const CATEGORY_ENTRY_NAME           = "magnolia"
  32.  
  33. const RDFS = Cc['@mozilla.org/rdf/rdf-service;1'].getService (Ci.nsIRDFService);
  34.  
  35. var gCompTK;
  36. function getCompTK() {
  37.   if (!gCompTK) {
  38.     gCompTK = Cc["@flock.com/singleton;1"].getService(Ci.flockISingleton)
  39.                         .getSingleton("chrome://browser/content/flock/services/common/load-compTK.js")
  40.                         .wrappedJSObject;
  41.   }
  42.   return gCompTK;
  43. }
  44.  
  45. var gTimers = [];  // For use with the scheduler
  46.  
  47. const MAGNOLIA_FAVICON = 'http://ma.gnolia.com/favicon.ico';
  48.  
  49. function loadLibraryFromSpec(aSpec) {
  50.   var loader = Cc['@mozilla.org/moz/jssubscript-loader;1']
  51.     .getService(Ci.mozIJSSubScriptLoader);
  52.  
  53.   loader.loadSubScript(aSpec);
  54. }
  55.  
  56. loadLibraryFromSpec("chrome://browser/content/flock/favorites/deliciousApi.js");
  57. loadLibraryFromSpec("chrome://browser/content/flock/favorites/onlineFavoritesBackend.js");
  58.  
  59.  
  60. function stringify (foo) {
  61.   if (foo==null) {
  62.     return '';
  63.   } else {
  64.     return foo;
  65.   }
  66. }
  67.  
  68. function dateify (foo) {
  69.   if (foo == null) {
  70.     return 0;
  71.   } else {
  72.     return foo.getTime ();
  73.   }
  74. }
  75.  
  76. function sanitize_tags (tags) {
  77.   return tags?tags.split(/[\s,]/).sort().join(','):'';
  78. }
  79.  
  80. function bookmarks_match (bm1, bm2) {
  81.   return (bm1.private == bm2.private && /* booleans - nice and easy */
  82.           stringify (bm1.name) == stringify (bm2.name) &&
  83.           stringify (bm1.description) == stringify (bm2.description) &&
  84.           sanitize_tags(bm1.tags) == sanitize_tags(bm2.tags) &&
  85.           dateify (bm1.datevalue) == dateify (bm2.datevalue));
  86. }
  87.  
  88.  
  89. function flockMagnoliaService() {
  90.   var obs = Cc["@mozilla.org/observer-service;1"].getService (Ci.nsIObserverService);
  91.   obs.addObserver (this, 'xpcom-shutdown', false);
  92.  
  93.   this._sync_worker_timer = null;
  94.  
  95.   this._state = 'idle';
  96.  
  97.   this.status = Ci.flockIWebService.STATUS_UNKNOWN;
  98.  
  99.   this.acUtils = Cc["@flock.com/account-utils;1"].getService(Ci.flockIAccountUtils);
  100.   this.url = "http://ma.gnolia.com";
  101.   this.api = new DeliciousAPI('https://ma.gnolia.com/api/mirrord/v1/');
  102.   this.mIsInitialized = false;
  103.   this._ctk = {
  104.     interfaces: [
  105.       "nsISupports",
  106.       "nsISupportsCString",
  107.       "nsIClassInfo",
  108.       "nsIObserver",
  109.       "nsITimerCallback",
  110.       "flockIWebService",
  111.       "flockIManageableWebService",
  112.       "flockIBookmarkWebService",
  113.       "flockIPollingService",
  114.     ],
  115.     shortName: "magnolia",
  116.     fullName: "Magnolia",
  117.     description: CLASS_NAME,
  118.     favicon: MAGNOLIA_FAVICON,
  119.     CID: CLASS_ID,
  120.     contractID: CONTRACT_ID,
  121.     accountClass: flockMagnoliaAccount
  122.   };
  123.   this._logger = Cc["@flock.com/logger;1"].createInstance (Ci.flockILogger);
  124.   this._logger.init ("magnolia");
  125.   this._profiler = Cc["@flock.com/profiler;1"].getService(Ci.flockIProfiler);
  126.  
  127.   this.init();
  128. }
  129.  
  130.  
  131. flockMagnoliaService.prototype.init = 
  132. function flockMagnoliaService_init ()
  133. {
  134.   // Prevent re-entry
  135.   if (this.mIsInitialized) return;
  136.   this.mIsInitialized = true;
  137.  
  138.   var evtID = this._profiler.profileEventStart("magnolia-init");
  139.   this._logger.info(".init()");
  140.  
  141.   // Determine whether this service has been disabled, and unregister if so.
  142.   this.prefService = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
  143.   if ( this.prefService.getPrefType(SERVICE_ENABLED_PREF) &&
  144.        !this.prefService.getBoolPref(SERVICE_ENABLED_PREF) )
  145.   {
  146.     this._logger.info("Pref "+SERVICE_ENABLED_PREF+" set to FALSE... not initializing.");
  147.     var catMgr = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
  148.     catMgr.deleteCategoryEntry("wsm-startup", CATEGORY_COMPONENT_NAME, true); 
  149.     catMgr.deleteCategoryEntry("flockWebService", CATEGORY_ENTRY_NAME, true); 
  150.     return;
  151.   }
  152.  
  153.   // get a coop interface to it
  154.   this._coop = Cc['@flock.com/singleton;1'].getService(Ci.flockISingleton).getSingleton('chrome://browser/content/flock/common/load-faves-coop.js').wrappedJSObject;
  155.  
  156.   if (this._coop.Service.exists ('urn:magnolia:service')) {
  157.     this._service = this._coop.get ('urn:magnolia:service');
  158.   } else {
  159.     this._service = new this._coop.Service ('urn:magnolia:service', {
  160.       name: 'magnolia',
  161.       desc: 'Magnolia'
  162.     });
  163.   }
  164.   this._service.serviceId = CONTRACT_ID;
  165.  
  166.   // Load Web Detective file
  167.   this.webDetective = this.acUtils.useWebDetective("magnolia.xml");
  168.   this._service.domains = this.webDetective.getString("magnolia", "domains", "gnolia.com");
  169.  
  170.   // Now that we know the service URN, we can register this service
  171.   // with the Web Service Manager.
  172.   this.urn = this._service.id();
  173.   this.bookmarksRootUrn = "urn:magnolia:bookmarks:";
  174.  
  175.   this._profiler.profileEventEnd(evtID, "");
  176. }
  177.  
  178. // BEGIN flockIWebService interface
  179. flockMagnoliaService.prototype.title = 'Magnolia';
  180.  
  181. flockMagnoliaService.prototype.icon = MAGNOLIA_FAVICON;
  182.  
  183. flockMagnoliaService.prototype.addAccountById =
  184. function flockMagnoliaService_addAccountById(aAccountID, aIsTransient, aListener)
  185. {
  186.   this._logger.debug("{flockIWebService}.addAccountById('"+aAccountID+"', "+aIsTransient+", aListener)");
  187.   var acct = onlineFavoritesBackend.createAccount(this, aAccountID, aIsTransient);
  188.   if (aListener) aListener.onSuccess(acct, "addAccount");
  189.  
  190.   return acct;
  191. }
  192.  
  193. flockMagnoliaService.prototype.removeAccount =
  194. function flockMagnoliaService_removeAccount(aUrn)
  195. {
  196.   this._logger.debug("{flockIWebService}.removeAccount('"+aUrn+"')"); 
  197.   onlineFavoritesBackend.removeAccount(this, aUrn);
  198. }
  199. // END flockIWebService interface
  200.  
  201.  
  202. // BEGIN flockIManageableWebService interface
  203. flockMagnoliaService.prototype.updateAccountStatusFromDocument =
  204. function flockMagnoliaService_updateAccountStatusFromDocument(aDocument)
  205. {
  206.   this._logger.debug("{flockIManageableWebService}.updateAccountStatusFromDocument()");
  207.   if (this.webDetective.detect("magnolia", "loggedout", aDocument, null)) {
  208.     this.acUtils.markAllAccountsAsLoggedOut(CONTRACT_ID);
  209.   } else if (this.webDetective.detect("magnolia", "loggedin", aDocument, null)) {
  210.     var results = Cc["@mozilla.org/hash-property-bag;1"].createInstance(Ci.nsIWritablePropertyBag2);
  211.     if (this.webDetective.detect("magnolia", "accountinfo", aDocument, results)) {
  212.       var accountID = results.getPropertyAsAString("accountid");
  213.       var accountURN = this.acUtils.getAccountURNById(this.urn, accountID);
  214.       this.acUtils.ensureOnlyAuthenticatedAccount(accountURN);
  215.     }
  216.   }
  217. }
  218. // END flockIManageableWebService interface
  219.  
  220. flockMagnoliaService.prototype._getAllTags =
  221. function (aUrn, aAccountId, aPassword, aListener) {
  222.   this._logger.info ('getAllTags(...)\n');
  223.   var svc = this;
  224.  
  225.   this.api.tagsGet ({
  226.     onError: function () {
  227.       // FIXME: report error?
  228.       /* BUG: 5705 */
  229.       svc._logger.error ('Delicious tags/get failed (in Magnolia)\n');
  230.       if (aListener)
  231.         aListener.onError ();
  232.     },
  233.     onSuccess: function (aResult, aTopic) {
  234.       // Delete existing tags and insert the new ones - there is probably a more efficient way to do it
  235.       var localBookmarks = svc._coop.get(svc.urn+':'+aAccountId+':bookmarks');
  236.       tagenum = localBookmarks.tag.enumerate();
  237.       while (tagenum.hasMoreElements()) {
  238.         var tag = tagenum.getNext();
  239.         localBookmarks.tag.remove(tag);
  240.       }
  241.       for (var i=0; i<aResult.length; i++) {
  242.         localBookmarks.tag.addOnce(aResult[i].tag);
  243.       }
  244.       // Tell the poller we're done
  245.       if (aListener)
  246.         aListener.onResult();
  247.     }
  248.   });
  249. }
  250.  
  251.  
  252. // flockIBookmarkWebService
  253. flockMagnoliaService.prototype.publish =
  254. function flockMagnoliaService_publish (aListener, aAccountId, aBookmark, aPrivate) {
  255.   this._logger.info("Publish ("+aBookmark.URL+","+aBookmark.name+") to "+aAccountId+"@Magnolia\n");
  256.   var accountUrn = this.urn+':'+aAccountId;
  257.   var password = this.acUtils.getPassword (accountUrn);
  258.   var svc = this;
  259.   var args = {
  260.     url: aBookmark.URL,
  261.     description: aBookmark.name,
  262.     extended: aBookmark.description,
  263.     tags: sanitize_tags(aBookmark.tags)
  264.   };
  265.   if (aPrivate)
  266.     args.shared = 'no';
  267.   this.api.call ('posts/add', args, {
  268.     onError: function () {
  269.       // FIXME: report error?
  270.       /* BUG: 5705 */
  271.       svc._logger.error ('Magnolia posts/add failed\n');
  272.       if (aListener)
  273.         aListener.onError (null, null, null);
  274.     },
  275.     onSuccess: function (aXML) {
  276.       if (!aXML || !aXML.documentElement ||
  277.           aXML.documentElement.tagName != 'result') {
  278.         // bad posts/all response
  279.         // FIXME: report error?
  280.         /* BUG: 5705 */
  281.         svc._logger.error ('Magnolia posts/add failed - invalid xml response');
  282.         if (aListener)
  283.           aListener.onError (null, null, null);
  284.         return;
  285.       }
  286.       var result = aXML.documentElement.getAttribute("code");
  287.       svc._logger.debug ("Result to posts/add: "+result);
  288.       if (result == "done") {
  289.         var localBookmarks = svc._coop.get(svc.urn+":"+aAccountId+":bookmarks");
  290.         var tags = aBookmark.tags.split(" ");
  291.         for (i in tags)
  292.           localBookmarks.tag.addOnce(tags[i]);
  293.         onlineFavoritesBackend.updateBookmark (svc, accountUrn, aBookmark, aPrivate);
  294.         if (aListener)
  295.           aListener.onSuccess(null, null);
  296.       }
  297.       else {
  298.         if (aListener)
  299.           aListener.onError(null, null, null);
  300.       }
  301.     }
  302.   }, password);
  303. }
  304.  
  305.  
  306. // flockIBookmarkWebService
  307. flockMagnoliaService.prototype.publishList =
  308. function (aListener, aAccountId, aBookmarkList, aPrivate) {
  309.   var delay = 1000; // 1 second between each query
  310.   var svc = this;
  311.   this._publishTimer = [];
  312.   var i = 0;
  313.   var sync = [];
  314.   var bookmarks = [];
  315.  
  316.   var sync = {
  317.     notify: function (timer) {
  318.       var bm = bookmarks.shift();
  319.       svc.publish(aListener, aAccountId, bm, aPrivate);
  320.     }
  321.   }
  322.  
  323.   while (aBookmarkList.hasMoreElements()) {
  324.     var bookmark = aBookmarkList.getNext().QueryInterface(Ci.flockIBookmark);
  325.     // Duplicate it because it's going to be removed too early
  326.     bookmarks[i] = {};
  327.     bookmarks[i].URL = bookmark.URL;
  328.     bookmarks[i].name = bookmark.name;
  329.     bookmarks[i].description = bookmark.description;
  330.     bookmarks[i].tags = bookmark.tags;
  331.     bookmarks[i].time = bookmark.time;
  332.     
  333.     this._logger.debug("==== Set a timer to "+i*delay+" for "+bookmarks[i].URL+"\n");
  334.     this._publishTimer[i] = Cc['@mozilla.org/timer;1'].createInstance(Ci.nsITimer);
  335.     this._publishTimer[i].initWithCallback(sync, i * delay, Ci.nsITimer.TYPE_ONE_SHOT);
  336.     i++;
  337.   }
  338. }
  339.  
  340.  
  341. // flockIBookmarkWebService
  342. flockMagnoliaService.prototype.remove =
  343. function (aListener, aAccountId, aUrl) {
  344.   this._logger.info("Remove "+aUrl+" from "+aAccountId+"@Magnolia\n");
  345.   var password = this.acUtils.getPassword (this.urn+':'+aAccountId);
  346.   var svc = this;
  347.   var args = { url: aUrl };
  348.   this.api.call ('posts/delete', args, {
  349.     onError: function () {
  350.       // FIXME: report error?
  351.       /* BUG: 5705 */
  352.       svc._logger.error ('Magnolia posts/delete failed\n');
  353.       if (aListener)
  354.         aListener.onError (null, null, null);
  355.     },
  356.     onSuccess: function (aXML) {
  357.       if (!aXML || !aXML.documentElement ||
  358.           aXML.documentElement.tagName != 'result') {
  359.         // bad posts/all response
  360.         // FIXME: report error?
  361.         /* BUG: 5705 */
  362.         svc._logger.error ('Magnolia posts/delete failed - invalid xml response');
  363.         if (aListener)
  364.           aListener.onError (null, null, null);
  365.         return;
  366.       }
  367.       var result = aXML.documentElement.getAttribute("code");
  368.       svc._logger.debug ("Result to posts/delete: "+result);
  369.       if (result == "done") {
  370.         onlineFavoritesBackend.destroyBookmark (svc, aAccountId, aUrl);
  371.         Cc["@flock.com/poller-service;1"].getService(Ci.flockIPollerService)
  372.           .forceRefresh(this.urn+":"+aAccountId+":bookmarks");
  373.         if (aListener)
  374.           aListener.onSuccess(null, null);
  375.       }
  376.       else {
  377.         if (aListener)
  378.           aListener.onError(null, null, null);
  379.       }
  380.     }
  381.   }, password);
  382. }
  383.  
  384.  
  385. // flockIBookmarkWebService
  386. flockMagnoliaService.prototype.exists =
  387. function flockMagnoliaService_publish (aAccountId, aURL) {
  388.   return this._coop.Bookmark.exists (this.urn+":"+aAccountId+":"+aURL);
  389. }
  390.  
  391.  
  392. flockMagnoliaService.prototype.getUserUrl = function (aAccountId) {
  393.   return "http://ma.gnolia.com/people/"+aAccountId;
  394. }
  395.  
  396. // flockIPollingService
  397. flockMagnoliaService.prototype.refresh =
  398. function flockMagnoliaService_refresh (aURN, aListener) {
  399.   var svc = this;
  400.   this._logger.info ('refresh (' + aURN + ')');
  401.  
  402.   if (!this._coop.OnlineBookmarksStream.exists (aURN))
  403.     throw "flockMagnoliaService: "+aURN+" can't be found";
  404.  
  405.   var bookmarks = this._coop.get (aURN);
  406.   var accountId = bookmarks.userid;
  407.   var accountUrn = this.urn + ":" + accountId;
  408.   // nsIPassword for auth for this sync
  409.   var password = this.acUtils.getPassword (accountUrn);
  410.  
  411.   this.api.postsAllIfNewer({
  412.     onError: function (aError) {
  413.       svc._logger.error ('Magnolia (Delicious API) posts/all failed: ['
  414.                          +aError.errorCode+"] "+aError.errorString+" (["
  415.                          +aError.serviceErrorCode+"] "+ aError.serviceErrorString+")");
  416.       var message;
  417.       switch (aError.errorCode) {
  418.         case aError.FAVS_UNAVAILABLE:
  419.           message = "Ma.gnolia.com reported that the service is currently unavailable; your bookmarks cannot be updated. Contact Magnolia for more informations.";
  420.           break;
  421.         case aError.FAVS_INVALID_AUTH:
  422.           message = "Ma.gnolia.com reported that your username or password is wrong. Please log in to Ma.gnolia.com again to update your authentication information.";
  423.           break;
  424.         default:
  425.           message = "Ma.gnolia.com returned an unknown error ["+aError.serviceErrorCode+"]";
  426.       }
  427.       onlineFavoritesBackend.showNotification(message);
  428.       if (aListener)
  429.         aListener.onError(aError);
  430.     },
  431.     onSuccess: function (aSubject, aTopic) {
  432.       if (aTopic == "updated") {
  433.         onlineFavoritesBackend.updateLocal(svc, aSubject, accountUrn);
  434.         // Now refresh the tag list (wait one sec)
  435.         var sync = {
  436.           notify: function (timer) {
  437.             svc._getAllTags (aURN, accountId, password, aListener);
  438.           }
  439.         }
  440.         svc._timer = Cc['@mozilla.org/timer;1'].createInstance(Ci.nsITimer);
  441.         svc._timer.initWithCallback(sync, 1000, Ci.nsITimer.TYPE_ONE_SHOT);
  442.       }
  443.       else {
  444.         // Tell the poller we're done
  445.         if (aListener)
  446.           aListener.onResult();
  447.       }
  448.     }
  449.   } , password, bookmarks.last_update_time);
  450. }
  451.  
  452. // nsIObserver
  453. flockMagnoliaService.prototype.observe = function (subject, topic, state) {
  454.   switch (topic) {
  455.     case 'xpcom-shutdown':
  456.       var obs = Cc["@mozilla.org/observer-service;1"]
  457.         .getService (Ci.nsIObserverService);
  458.       obs.removeObserver (this, 'xpcom-shutdown');
  459.       return;
  460.   }
  461. }
  462.  
  463. /******************************************************************************
  464.  * XPCOM Functions for construction and registration
  465.  ******************************************************************************/
  466.  
  467. function createModule(aParams) {
  468.   return {
  469.     registerSelf: function (aCompMgr, aFileSpec, aLocation, aType) {
  470.       aCompMgr.QueryInterface(Ci.nsIComponentRegistrar);
  471.       aCompMgr.registerFactoryLocation( aParams.CID, aParams.componentName,
  472.                                         aParams.contractID, aFileSpec,
  473.                                         aLocation, aType );
  474.       var catMgr = Cc["@mozilla.org/categorymanager;1"]
  475.         .getService(Ci.nsICategoryManager);
  476.       if (!aParams.categories) { aParams.categories = []; }
  477.       for (var i = 0; i < aParams.categories.length; i++) {
  478.         var cat = aParams.categories[i];
  479.         catMgr.addCategoryEntry( cat.category, cat.entry,
  480.                                  cat.value, true, true ); 
  481.       }
  482.     },
  483.     getClassObject: function (aCompMgr, aCID, aIID) {
  484.       if (!aCID.equals(aParams.CID)) { throw Cr.NS_ERROR_NO_INTERFACE; }
  485.       if (!aIID.equals(Ci.nsIFactory)) { throw Cr.NS_ERROR_NOT_IMPLEMENTED; }
  486.       return { // Factory
  487.         createInstance: function (aOuter, aIID) {
  488.           if (aOuter != null) { throw Cr.NS_ERROR_NO_AGGREGATION; }
  489.           var comp = new aParams.componentClass();
  490.           if (aParams.implementationFunc) { aParams.implementationFunc(comp); }
  491.           return comp.QueryInterface(aIID);
  492.         }
  493.       };
  494.     },
  495.     canUnload: function (aCompMgr) { return true; }
  496.   };
  497. }
  498.  
  499. // NS Module entrypoint
  500. function NSGetModule(aCompMgr, aFileSpec) {
  501.   return createModule({
  502.     componentClass: flockMagnoliaService,
  503.     CID: CLASS_ID,
  504.     contractID: CONTRACT_ID,
  505.     componentName: CATEGORY_COMPONENT_NAME,
  506.     implementationFunc: function (aComp) { getCompTK().addAllInterfaces(aComp); },
  507.     categories: [
  508.       { category: "wsm-startup", entry: CATEGORY_COMPONENT_NAME, value: CONTRACT_ID },
  509.       { category: "flockWebService", entry: CATEGORY_ENTRY_NAME, value: CONTRACT_ID }
  510.     ]
  511.   });
  512. }
  513.  
  514.  
  515. // =======================================================
  516. // ========== BEGIN flockMagnoliaAccount class ==========
  517. // =======================================================
  518.  
  519. function flockMagnoliaAccount()
  520. {
  521.   this._coop = Cc['@flock.com/singleton;1'].getService(Ci.flockISingleton)
  522.                          .getSingleton('chrome://browser/content/flock/common/load-faves-coop.js')
  523.                          .wrappedJSObject;
  524.   this.acUtils = Cc["@flock.com/account-utils;1"].getService(Ci.flockIAccountUtils);
  525.   this.service = Cc[CONTRACT_ID].getService(Ci.flockIWebService);
  526.   this._ctk = {
  527.     interfaces: [
  528.       "nsISupports",
  529.       "flockIWebServiceAccount",
  530.       "flockIBookmarkWebServiceAccount"
  531.     ]
  532.   };
  533.   this._logger = Cc["@flock.com/logger;1"].createInstance (Ci.flockILogger);
  534.   this._logger.init ("magnolia");
  535.   getCompTK().addAllInterfaces(this);
  536. }
  537.  
  538. // BEGIN flockIWebServiceAccount interface
  539. flockMagnoliaAccount.prototype.activate =
  540. function flockMagnoliaAccount_activate(aListener)
  541. {
  542.   this._logger.debug("{flockIWebServiceAccount}.activate()");
  543.   var acctCoopObj = this._coop.get(this.urn);
  544.   acctCoopObj.isAuthenticated = true;
  545.   this._coop.get(this.urn + ':bookmarks').isPollable = true;
  546. }
  547.  
  548. flockMagnoliaAccount.prototype.keep =
  549. function flockMagnoliaAccount_keep(aListener)
  550. {
  551.   this._logger.debug("{flockIWebServiceAccount}.keep()");
  552.   this._coop.get(this.urn).isTransient = false;
  553.   this._coop.get(this.urn+":bookmarks").isTransient = false;
  554.   this.acUtils.makeTempPasswordPermanent(this.urn);
  555.  
  556.   if (aListener) {
  557.     aListener.onSuccess(this, "keep");
  558.   }
  559. }
  560.  
  561. // END flockIWebServiceAccount interface
  562.